package mylab.starters.mybatis.template.dto;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import mylab.base.model.dto.DTO;
import mylab.starters.mybatis.utils.MpUtils;
import mylab.starters.mybatis.utils.QueryUtil;
import mylab.starters.mybatis.utils.query.QC;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel("自定义查询参数")
public class QueryParam extends DTO {

    /**
     * 属性序列，逗号分隔
     */
    @ApiModelProperty(value = "待查询的属性序列，逗号分隔", example = "id,name")
    private String props;

    /**
     * 查询条件
     */
    @ApiModelProperty(value = "自定义查询条件列表")
    private List<QC> qcs;

    /**
     * 排序条件，逗号分隔
     * eg: "id asc, name desc"
     */
    @ApiModelProperty(value = "排序参数,逗号分隔", example = "id asc,name desc")
    private String orders;

    /**
     * 最多查询条数
     */
    @ApiModelProperty("最多查询条数")
    private Integer limit;

    @ApiModelProperty(value = "扩展参数", notes = "map 中的 key 遵循约定大于配置的原则")
    private Map<String, Object> extra = new HashMap<>(8);

    @JsonIgnore
    public <T> QueryWrapper<T> wrapper(Class<T> entityClass) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper = QueryUtil.build(wrapper, qcs, entityClass);

        if (CharSequenceUtil.isNotBlank(props)) {
            List<String> columns = Lists.newArrayList();
            for (String property : Splitter.on(",").omitEmptyStrings().splitToList(props)) {
                String column = null;
                try {
                    column = MpUtils.getColumnName(entityClass, property.trim());
                } catch (Exception ignored) {
                }

                Assert.notNull(column, "查询字段不可识别:" + property);
                columns.add(column);
            }
            wrapper.select(columns.toArray(new String[]{}));
        }

        if (CharSequenceUtil.isNotBlank(orders)) {
            QueryWrapper<T> finalWrapper = wrapper;
            Splitter.on(",").splitToList(orders.trim()).forEach(o -> {
                List<String> oneItem = Splitter.on(" ").trimResults().splitToList(o.trim());
                String column = null;
                try {
                    column = MpUtils.getColumnName(entityClass, oneItem.get(0));
                } catch (Exception ignored) {
                }
                Assert.notNull(column, "排序字段不可识别:" + oneItem);

                boolean isAsc = false;
                if (oneItem.size() > 1) {
                    isAsc = CharSequenceUtil.equalsAny(oneItem.get(1), "asc", "ascending", "ascend");
                }
                finalWrapper.orderBy(true, isAsc, column);
            });
        }

        if (limit != null && limit > 0) {
            Assert.isTrue(limit <= 1000, "limit 值不得大于1000");
            wrapper.last(CharSequenceUtil.format("limit {}", limit));
        }

        return wrapper;
    }
}
